/*
 * Copyright (c) 2009. Silenus Consultoria, S.L.
 */
package es.silenus.detecta.controller;

import es.silenus.detecta.dao.*;

import es.silenus.detecta.model.*;

import es.silenus.detecta.service.AlfrescoService;

import es.silenus.detecta.task.Task;

import org.apache.commons.io.FilenameUtils;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;

import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import java.io.File;
import java.io.IOException;

import java.sql.Date;

import java.text.ParseException;
import java.text.SimpleDateFormat;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
 * The Class FileUploadController.
 *
 * @author <a href="mailto:je.macineiras@silenus-consultoria.es">Jos&eacute; Enrique Garc&iacute;a
 * 				 Maci&ntilde;eiras</a>.
 */
public class FileUploadController extends BaseController {
	/**
	 * Logger for this class.
	 */
	private static final Log LOG = LogFactory.getLog(FileUploadController.class);

	/**
	 * JSON success text.
	 */
	private static final String JSON_SUCCESS_TEXT = "{success: true}";

	/**
	 * JSON error text.
	 */
	private static final String JSON_ERROR_TEXT = "{success: false}";

	/**
	 * The imported file.
	 */
	private ImportedFileDAO importedFileDAO;

	/**
	 * The organization dao.
	 */
	private OrganizationDAO organizationDAO;

	/**
	 * The survey answer header.
	 */
	private SurveyAnswerHeaderImportedDAO surveyAnswerHeaderImportedDAO;

	/**
	 * The survey unit answer import dao.
	 */
	private SurveyUnitAnswerImportedDAO surveyUnitAnswerImportedDAO;

	/**
	 * The alfresco service.
	 */
	private AlfrescoService alfrescoService;

	/**
	 * The import folder name.
	 */
	private String importFolderName;

	/**
	 * The import file task.
	 */
	private Task importFileTask;

/**
   * Constructor.
   */
	public FileUploadController() {
		importFolderName = "Imported Files";
	}

	/**
	 * Sets the survey unit answer import dao.
	 *
	 * @param surveyUnitAnswerImportedDAO the new survey unit answer import dao
	 */
	public void setSurveyUnitAnswerImportedDAO(final SurveyUnitAnswerImportedDAO surveyUnitAnswerImportedDAO) {
		this.surveyUnitAnswerImportedDAO = surveyUnitAnswerImportedDAO;
	}

	/**
	 * Sets the survey answer header import dao.
	 *
	 * @param surveyAnswerHeaderImportedDAO the new survey answer header import dao
	 */
	public void setSurveyAnswerHeaderImportedDAO(final SurveyAnswerHeaderImportedDAO surveyAnswerHeaderImportedDAO) {
		this.surveyAnswerHeaderImportedDAO = surveyAnswerHeaderImportedDAO;
	}

	/**
	 * Sets the organization dao.
	 *
	 * @param organizationDAO the new organization dao
	 */
	public void setOrganizationDAO(final OrganizationDAO organizationDAO) {
		this.organizationDAO = organizationDAO;
	}

	/**
	 * Sets the imported file.
	 *
	 * @param importedFile the new imported file
	 */
	public void setImportedFileDAO(final ImportedFileDAO importedFile) {
		this.importedFileDAO = importedFile;
	}

	/**
	 * Sets the alfresco service.
	 *
	 * @param alfrescoService the alfresco service.
	 */
	public void setAlfrescoService(final AlfrescoService alfrescoService) {
		this.alfrescoService = alfrescoService;
	}

	/**
	 * Sets the import folder name.
	 *
	 * @param importFolderName the import folder name.
	 */
	public void setImportFolderName(final String importFolderName) {
		this.importFolderName = importFolderName;
	}

	/**
	 * Sets the import file task.
	 *
	 * @param importFileTask the import file task.
	 */
	public void setImportFileTask(final Task importFileTask) {
		this.importFileTask = importFileTask;
	}

	/**
	 * Find files.
	 *
	 * @param request the request
	 * @param response the response
	 *
	 * @return the string
	 *
	 * @throws ServletRequestBindingException the servlet request binding exception
	 * @throws ParseException the Date parse Exception
	 */
	public String findFiles(final HttpServletRequest request, final HttpServletResponse response)
		throws ServletRequestBindingException, ParseException {
		User current = getUser(request);

		final SimpleDateFormat dateFormater = new SimpleDateFormat("dd/MM/yyyy");

		final int idOrganization = current.getOrganization().getId();

		Map<String, Object> sample = new HashMap<String, Object>();

		sample.put("organizationId", idOrganization);

		String filename = ServletRequestUtils.getStringParameter(request, "filename", null);

		if(filename != null) {
			sample.put("filename", filename);
		}

		int status = ServletRequestUtils.getIntParameter(request, "status", 0);

		if(status > 0) {
			sample.put("status", status);
		}

		String temp = ServletRequestUtils.getStringParameter(request, "fromImportDate", null);

		if(temp != null) {
			sample.put("fromImportDate", dateFormater.parse(temp));
		}

		temp = ServletRequestUtils.getStringParameter(request, "toImportDate", null);

		if(temp != null) {
			sample.put("toImportDate", dateFormater.parse(temp));
		}


		int start = ServletRequestUtils.getIntParameter(request, "start", 0);
		int limit = ServletRequestUtils.getIntParameter(request, "limit", 20);
		String[] sortFields = request.getParameterValues("sort");
		String[] sortDirections = request.getParameterValues("dir");

		Page<ImportedFile> importedFileList = importedFileDAO.findByExample(
				sample, start, limit, sortFields, sortDirections);

		request.setAttribute("page", importedFileList);

		return "secure/import/imported-file-list";
	}

	/**
	 * Upload file.
	 *
	 * @param request the request
	 * @param response the response
	 *
	 * @return the string
	 *
	 * @throws ServletRequestBindingException the servlet request binding exception
	 * @throws ParseException the parse exception
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	public String uploadFile(final HttpServletRequest request, final HttpServletResponse response)
		throws ServletRequestBindingException, ParseException, IOException {
		if(!(request instanceof MultipartHttpServletRequest)) {
			response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Expected multipart request");

			return null;
		}

		try {
			final User current = getUser(request);

			// Prepare file
			final MultipartFile uploadedFile = ((MultipartHttpServletRequest)request).getFile("file");

			final String fileName = uploadedFile.getOriginalFilename();


			String seedName = FilenameUtils.getBaseName(fileName);
			if(seedName.length() < 3) {
				seedName += "___";
			}

			final File tempFile = File.createTempFile(
					seedName,
					FilenameUtils.EXTENSION_SEPARATOR_STR + FilenameUtils.getExtension(fileName));

			// Create imported file
			ImportedFile importedFile = new ImportedFile();

			// Upload file
			uploadedFile.transferTo(tempFile);

			String mimeType = getServletContext().getMimeType(tempFile.getName());

			StringBuilder remoteFolderPath = new StringBuilder(current.getOrganization().getName());
			remoteFolderPath.append("/");
			remoteFolderPath.append(importFolderName);

			alfrescoService.uploadFile(tempFile, mimeType, request.getCharacterEncoding(), remoteFolderPath.toString());

			// Persist imported file
			importedFile.setFilename(tempFile.getName());
			importedFile.setOrganization(current.getOrganization());
			importedFileDAO.save(importedFile);

			Map<String, Object> parameters = new HashMap<String, Object>();

			parameters.put("importedFile", importedFile);
			parameters.put("file", tempFile);

			// Launch task
			importFileTask.setParameters(parameters);
			importFileTask.execute();

			printHTML(response, JSON_SUCCESS_TEXT);
		} catch(Throwable e) {
			LOG.error("Error handling file upload", e);
			printHTML(response, JSON_ERROR_TEXT);
		}

		return null;
	}

	/**
	 * Process a file, importing its contents already validated into database.
	 *
	 * @param request the request
	 * @param response the response
	 *
	 * @return the string
	 *
	 * @throws ServletRequestBindingException the servlet request binding exception
	 * @throws ParseException if something goes wrong.
	 */
	public String processFile(final HttpServletRequest request, final HttpServletResponse response)
		throws ServletRequestBindingException, ParseException {
		long[] ids = ServletRequestUtils.getRequiredLongParameters(request, "id");

		for(long id : ids) {
			importedFileDAO.validate(id);
			importedFileDAO.process(id);
		}

		return JSON_SUCCESS_VIEW;
	}

	/**
	 * Delete import file contents, file will be kept for statistics.
	 *
	 * @param request the request
	 * @param response the response
	 *
	 * @return the string
	 *
	 * @throws ServletRequestBindingException the servlet request binding exception
	 * @throws ParseException if something goes wrong.
	 */
	public String deleteFile(final HttpServletRequest request, final HttpServletResponse response)
		throws ServletRequestBindingException, ParseException {
		long[] ids = ServletRequestUtils.getRequiredLongParameters(request, "id");

		for(long id : ids) {
			importedFileDAO.clear(id);
		}

		return JSON_SUCCESS_VIEW;
	}

	/**
	 * Validates the given files.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 *
	 * @throws ServletRequestBindingException if something goes wrong.
	 */
	public String validateFile(final HttpServletRequest request, final HttpServletResponse response)
		throws ServletRequestBindingException {
		long[] ids = ServletRequestUtils.getRequiredLongParameters(request, "id");

		for(long id : ids) {
			importedFileDAO.validate(id);
		}

		return JSON_SUCCESS_VIEW;
	}

	/**
	 * Find imported survey.
	 *
	 * @param request the request
	 * @param response the response
	 *
	 * @return the string
	 *
	 * @throws ServletRequestBindingException the servlet request binding exception
	 */
	public String findImportedHeaders(final HttpServletRequest request, final HttpServletResponse response)
		throws ServletRequestBindingException {
		User current = getUser(request);
		int idOrganization = current.getOrganization().getId();

		long idFile = ServletRequestUtils.getRequiredLongParameter(request, "id");

		Map<String, Object> sample = new HashMap<String, Object>();

		sample.put("idFile", idFile);
		sample.put("organizationId", idOrganization);

		int start = ServletRequestUtils.getIntParameter(request, "start", 0);
		int limit = ServletRequestUtils.getIntParameter(request, "limit", 20);
		String[] sortFields = request.getParameterValues("sort");
		String[] sortDirections = request.getParameterValues("dir");

		Page<SurveyAnswerHeaderImported> page = surveyAnswerHeaderImportedDAO.findByExample(
				sample, start, limit, sortFields, sortDirections);

		request.setAttribute("page", page);

		return "secure/import/imported-survey-list";
	}

	/**
	 * Saves an imported header.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 *
	 * @throws ServletRequestBindingException if something goes wrong.
	 */
	public String saveImportedHeaders(final HttpServletRequest request, final HttpServletResponse response)
		throws ServletRequestBindingException {
		long[] ids = ServletRequestUtils.getRequiredLongParameters(request, "id");
		String[] entityIds = ServletRequestUtils.getRequiredStringParameters(request, "entityId");
		String[] surveyCodes = ServletRequestUtils.getRequiredStringParameters(request, "surveyCode");
		String[] actionCodes = ServletRequestUtils.getRequiredStringParameters(request, "actionCode");
		int[] internetConnections = ServletRequestUtils.getRequiredIntParameters(request, "internetConnection");
		String[] creationDates = ServletRequestUtils.getRequiredStringParameters(request, "creationDate");
		String[] councilIds = ServletRequestUtils.getRequiredStringParameters(request, "councilId");
		
		final SimpleDateFormat dateFormater = new SimpleDateFormat("dd/MM/yyyy");

		SurveyAnswerHeaderImported header;
		Date date;

		for(int i = 0; i < ids.length; ++i) {
			header = surveyAnswerHeaderImportedDAO.findById(ids[i]);

			if(header != null) {
				header.setEntityId(entityIds[i]);
				header.setSurveyCode(surveyCodes[i]);
				header.setActionCode(actionCodes[i]);
				header.setInternetConnection(internetConnections[i]);
				header.setCouncilId(councilIds[i]);
				try {
					date = new Date(dateFormater.parse(creationDates[i]).getTime());
					header.setCreationDate(date);
				} catch(ParseException e) {
					// do nothing
				}

				surveyAnswerHeaderImportedDAO.update(header);
			}
		}

		return JSON_SUCCESS_VIEW;
	}

	/**
	 * Find imported survey.
	 *
	 * @param request the request
	 * @param response the response
	 *
	 * @return the string
	 *
	 * @throws ServletRequestBindingException the servlet request binding exception
	 */
	public String deleteImportedHeaders(final HttpServletRequest request, final HttpServletResponse response)
		throws ServletRequestBindingException {
		long[] keys = ServletRequestUtils.getRequiredLongParameters(request, "id");
		ArrayList<Long> keyList = new ArrayList<Long>(keys.length);

		for(long key : keys) {
			keyList.add(key);
		}

		surveyAnswerHeaderImportedDAO.removeByKey(keyList);

		return JSON_SUCCESS_VIEW;
	}

	/**
	 * Find imported unit answers of a given survey answer.
	 *
	 * @param request the request
	 * @param response the response
	 *
	 * @return the string
	 *
	 * @throws ServletRequestBindingException the servlet request binding exception
	 */
	public String findImportedUnits(final HttpServletRequest request, final HttpServletResponse response)
		throws ServletRequestBindingException {
		long idHeader = ServletRequestUtils.getRequiredLongParameter(request, "idHeader");

		Map<String, Object> sample = new HashMap<String, Object>();

		sample.put("idHeader", idHeader);

		int start = ServletRequestUtils.getIntParameter(request, "start", 0);
		int limit = ServletRequestUtils.getIntParameter(request, "limit", 20);
		String[] sortFields = request.getParameterValues("sort");
		String[] sortDirections = request.getParameterValues("dir");

		Page<SurveyUnitAnswerImported> page = surveyUnitAnswerImportedDAO.findByExample(
				sample, start, limit, sortFields, sortDirections);

		request.setAttribute("page", page);

		return "secure/import/imported-survey-unit-answer-list";
	}

	/**
	 * Save an imported unit answer from a imported survey answer.
	 *
	 * @param request the request
	 * @param response the response
	 *
	 * @return the string
	 *
	 * @throws ServletRequestBindingException the servlet request binding exception
	 */
	public String saveImportedUnits(final HttpServletRequest request, final HttpServletResponse response)
		throws ServletRequestBindingException {
		long header = ServletRequestUtils.getRequiredLongParameter(request, "header");

		int[] questionNumbers = ServletRequestUtils.getRequiredIntParameters(request, "questionNumber");
		int[] preferences = ServletRequestUtils.getRequiredIntParameters(request, "preference");
		String[] questionCodes = ServletRequestUtils.getRequiredStringParameters(request, "questionCode");

		SurveyUnitAnswerImported unit;

		for(int i = 0; i < questionNumbers.length; ++i) {
			unit = surveyUnitAnswerImportedDAO.findById(header, questionNumbers[i]);

			if(unit != null) {
				unit.setPreference(TrainingPreference.getById(preferences[i]));
				unit.setQuestionCode(questionCodes[i]);

				surveyUnitAnswerImportedDAO.save(unit);
			}
		}


		return JSON_SUCCESS_VIEW;
	}

	/**
	 * Remove an imported unit answer from a imported survey answer.
	 *
	 * @param request the request
	 * @param response the response
	 *
	 * @return the string
	 *
	 * @throws ServletRequestBindingException the servlet request binding exception
	 */
	public String deleteImportedUnits(final HttpServletRequest request, final HttpServletResponse response)
		throws ServletRequestBindingException {
		long idHeader = ServletRequestUtils.getRequiredLongParameter(request, "header");
		int[] questionNumbers = ServletRequestUtils.getRequiredIntParameters(request, "questionNumber");

		SurveyUnitAnswerImported importedSurveyUnit;

		for(int questionNumber : questionNumbers) {
			importedSurveyUnit = surveyUnitAnswerImportedDAO.findById(idHeader, questionNumber);
			surveyUnitAnswerImportedDAO.remove(importedSurveyUnit);
		}

		return JSON_SUCCESS_VIEW;
	}
}
